package com.gzsxy.esjy.bus.log.aspect;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gzsxy.esjy.bus.service.LoginlogService;
import com.gzsxy.esjy.common.base.util.FileUtils;
import com.gzsxy.esjy.common.base.util.RequestHolder;
import com.gzsxy.esjy.common.base.util.RequestUtil;
import com.gzsxy.esjy.common.base.util.ThreadPoolUtil;
import com.gzsxy.esjy.service.base.dto.request.LoginLogRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;


import javax.servlet.http.HttpServletRequest;

import java.util.Date;
import java.util.Enumeration;

/**
 * @author xiaolong
 * @version 1.0
 * @description: 登录日志
 * @date 2022/5/3 16:26
 */
@Aspect //标识切面
@Component
@ConditionalOnProperty(name = "gzsxy.aspect.enable", havingValue = "true")
public class LoginAspect {

    private static final Logger log = LoggerFactory.getLogger(LoginAspect.class);


    @Autowired
    private LoginlogService loginlogService;

    @Pointcut("execution(* com.gzsxy.esjy..auth..ApiAuthController.login(..))")
    public void ControllerAspect(){
    }

    /**
     * 配置环绕通知,使用在方法logPointcut()上注册的切入点
     *
     * @param joinPoint join point for advice
     */
    @Before(value = "ControllerAspect()")
    public void doBefore(JoinPoint joinPoint) {

        HttpServletRequest request = RequestHolder.getHttpServletRequest();
        if (request != null) {
            // 记录下请求内容
            log.info("URL : {}", request.getRequestURL().toString());
            log.info("HTTP_METHOD :{} ", request.getMethod());
            log.info("IP : {}", request.getRemoteAddr());
            log.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
            log.info("ARGS : " + FileUtils.obiectToJson(joinPoint.getArgs()));
            Enumeration<String> enu = request.getParameterNames();
            while (enu.hasMoreElements()) {
                String name = enu.nextElement();
                log.info("name:{},value:{}", name, request.getParameter(name));
            }
        } else {
            log.error("ServletRequestAttributes为空！");
        }
    }






    /**
     * 正常返回通知，拦截用户操作日志，连接点正常执行完成后执行， 如果连接点抛出异常，则不会执行
     *
     * @param joinPoint 切入点
     * @param keys      返回结果
     */
    @AfterReturning(value = "ControllerAspect()", returning = "keys")
    public void saveLogin(JoinPoint joinPoint, Object keys) {
        HttpServletRequest request = RequestHolder.getHttpServletRequest();
        if (request != null) {
            LoginLogRequest logRequest = new LoginLogRequest();
            JSONObject parse = (JSONObject) JSONObject.parse(JSON.toJSONString(keys));
            JSONObject data = parse.getJSONObject("data");
            logRequest.setUserName(data.getString("userName"));
            logRequest.setSchool(data.getString("school"));
            // 返回结果
            logRequest.setResponseParam(FileUtils.obiectToJson(keys));
            // 请求IP
            logRequest.setIp(RequestUtil.getClientIp(request));
            logRequest.setLoginTime(new Date());
            logRequest.setBrowserName(RequestHolder.getBrowserName(request));
            logRequest.setOsName(RequestHolder.getOsName(request));
            logRequest.setVersion(RequestHolder.getBrowserVersion(request));
            //成功执行成功入库 持久化(存储到数据或者ES，可以考虑用线程池)
            ThreadPoolUtil.getPool().execute(new SaveSystemLogThread(logRequest, loginlogService));
        } else {
            log.error("ServletRequestAttributes为空！");
        }
    }



    /**
     * 保存日志至数据库
     */
    private static class SaveSystemLogThread implements Runnable {

        private LoginLogRequest log;
        private LoginlogService loginlogService;

        public SaveSystemLogThread(LoginLogRequest olLog, LoginlogService loginlogService) {
            this.log = olLog;
            this.loginlogService = loginlogService;
        }

        @Override
        public void run() {
            loginlogService.addLoginlog(log);
        }
    }


}
